package com.fjwt.gz.coupon.gtpay.demo;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * RSA分段加密工具类
 *
 */
public class RSAUtilSegment {
    private static final String ALGORITHM = "RSA";

    /**
     * 加密算法
     */
    private static final String CIPHER_DE = "RSA";

    /**
     * 解密算法
     */
    private static final String CIPHER_EN = "RSA";

    /**
     * 密钥长度
     */
    private static final Integer KEY_LENGTH = 1024;

    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;

    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;
    // 密钥长度 1024 bit ；密钥格式：PKCS#8
    // 公
    public static String gt = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8jZkBuFY+AWs0hJ66arR0Ixbm" +
            "3lPOAgC/2fo1aS+g3rLdKtM9eucoLaPtr44blo67O1/sqFrppE+DeizslGd8bcg6" +
            "Nisc49pIWvlHHHihl3LoqQBzOKmRs5vTpqNQm6I2oyeTWjCrnbv7SGl4mHk5bqAe" +
            "QWG3W7mKnRTUBtmHYQIDAQAB";

    // 私
    public static String gts = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALyNmQG4Vj4BazSE" +
            "nrpqtHQjFubeU84CAL/Z+jVpL6Dest0q0z165ygto+2vjhuWjrs7X+yoWumkT4N6" +
            "LOyUZ3xtyDo2Kxzj2kha+UcceKGXcuipAHM4qZGzm9Omo1CbojajJ5NaMKudu/tI" +
            "aXiYeTluoB5BYbdbuYqdFNQG2YdhAgMBAAECgYAuETps3SjVBWu37R8K1L86EMir" +
            "p246Sur79LnZCtYEK+TvfGMYBksr2drPW7EQtHwy6pLJM2ji5K44pUUMmEWgCX+K" +
            "qvkAYMKLlmLt41TbVmbAyPCbphusXiv2vcDoyDhNwezEy7cutjPuJFGE9e+U618E" +
            "5eRyntm3KSTyqNreQQJBAOfKbrDdmXdmfrye+gZK/qXNo6MJJEhZD+hGj810kRgv" +
            "FKlfDRhF5dTpaVuPuBzdhb8mRD23G20te8Ucs591nrUCQQDQPxZeTB3nUkVqMQwz" +
            "//77lrOZ7cUkgpsW+6dUjTqKBPnHOIZgrajbInDLR/wYSDLnHYAlqttRy5gaWYdW" +
            "e4V9AkBa2JZlr5S0nXFS0CRCTyZbKavW/IBB8tYvPWijJ+quRdWdRGnHd63Ksuje" +
            "QAfzGEeRUZgxcBDJy6fU65jjCKB5AkEAll+360fToCJMda4NPc9xdIMSFekYHpEh" +
            "JKt73RZOWzPUmgM7JbzA3dw0ztWgOHiKKVGoI4sI7Du0DfLwQ4bWkQJBAKQPtRfv" +
            "Mx7lGSJIr2q5/dZAYJMiYBaC0cgnaxcQphuhNKpSB3jE6O3DljNq8/RuUh7RZOqG" +
            "uZO5bEI+3+X3sUE=";
    /**
     * 公钥加密
     *
     * @param data 待加密的数据
     * @param publicKey 公钥
     * @return byte[]
     */
    public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
        // 得到公钥
        byte[] keyBytes = Base64.decodeBase64(publicKey.getBytes());
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        Key key = keyFactory.generatePublic(x509EncodedKeySpec);
        // 加密数据，分段加密
        Cipher cipher = Cipher.getInstance(CIPHER_EN);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        int inputLength = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        while (inputLength - offset > 0) {
            if (inputLength - offset > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offset, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offset, inputLength - offset);
            }
            out.write(cache, 0, cache.length);
            i++;
            offset = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return encryptedData;
    }

    /**
     * 私钥解密
     *
     * @param data 加密后的数据
     * @param privateKey 私钥
     * @return byte[]
     */
    public static byte[] decryptByPrivateKey(byte[] data, String privateKey) throws Exception {
        // 得到私钥
        byte[] keyBytes = Base64.decodeBase64(privateKey.getBytes());
        PKCS8EncodedKeySpec pKCS8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        Key key = keyFactory.generatePrivate(pKCS8EncodedKeySpec);
        // 解密数据，分段解密
        Cipher cipher = Cipher.getInstance(CIPHER_DE);
        cipher.init(Cipher.DECRYPT_MODE, key);
        int inputLength = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offset = 0;
        byte[] cache;
        int i = 0;
        byte[] tmp;
        while (inputLength - offset > 0) {
            if (inputLength - offset > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(data, offset, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offset, inputLength - offset);
            }
//            out.write(cache, 0, cache.length);
            out.write(cache);
            i++;
            offset = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return decryptedData;
    }

    public static void main(String[] args) throws Exception{
        String message = "{\n" +
                "    \"create_time\":\"2023-04-27T09:09:56+08:00\",\n" +
                "    \"available_end_time\":\"2023-07-16T23:59:59+08:00\",\n" +
                "    \"singleitem\":false,\n" +
                "    \"description\":\"\",\n" +
                "    \"stock_id\":\"17423407\",\n" +
                "    \"coupon_name\":\"渝中邮政优惠券1\",\n" +
                "    \"no_cash\":false,\n" +
                "    \"stock_creator_mchid\":\"1501970731\",\n" +
                "    \"coupon_id\":\"44473739915\",\n" +
                "    \"normal_coupon_information\":{\n" +
                "        \"coupon_amount\":299,\n" +
                "        \"transaction_minimum\":300\n" +
                "    },\n" +
                "    \"consume_information\":{\n" +
                "        \"transaction_id\":\"4200001796202304276079076804\",\n" +
                "        \"consume_time\":\"2023-04-27T09:10:12+08:00\",\n" +
                "        \"consume_mchid\":\"1500947831\"\n" +
                "    },\n" +
                "    \"coupon_type\":\"NORMAL\",\n" +
                "    \"available_begin_time\":\"2023-04-18T00:00:00+08:00\",\n" +
                "    \"status\":\"USED\",\"sign\":\"8e8d52eebf59d0ade059656d0ccf5911\"\n" +
                "\n" +
                "}";
        //      对返回的参数进行rsa加密
        String encryptStr = new String(Base64.encodeBase64(RSAUtilSegment.encryptByPublicKey(message.getBytes(), gt)));
        System.out.println(encryptStr);

//        String str = "Al/rQ+1Nuk2qoewBz2zPJuAhFJT+QwBZVyIlYM7j2WkN2HIqZCEQUzxr2D6b1S2SVB89uQIA0TqerYhw1BhBGYkzPqli2fNNj68u36uPu6m/Pxn3gF9hkmjCPyIo/1WvVL059lWo1JGtXdFwbWfRxLH57KsmmPQkVeq5v5b9usxCr9Dt9OAXLwHRSn0w5nY9Q+Iev69UsHIJDDHFTtIOxTLg5ZltMu2dOglOeofxWXQxiaTrpw4ZUUGF6Xai8g0vrk20PCDh5UitWe2ATm9KOR5VNud3pdJrhbRUGm88vuPkCjdAqURM+In3R+jj1Bw+6+iKD5SPpugxIpx2+SE97rexm6YazIy3MsSvyvFNh0wKgIlqX3Po/ZVp23N60r80Sn2OKdt8qFPOzQFvFiQqN9OHvGJYOKxqIVRSZbS8452Kfz+YVObkApZe6v/ue7/IXcNEKx+PDb2akOAamPyOEfexPed3j5o7R+TgPYehu6YAM2rybjzAeQj5qZSpVGgz";
////        RSAUtilSegment.decryptByPrivateKey(Base64.decodeBase64(requestStr), privateKey)
//        byte[] decryptStrByte = RSAUtilSegment.decryptByPrivateKey(Base64.decodeBase64(str), privateKey);
//        System.out.println(new String(decryptStrByte));
    }
}
